package org.dhbw.cocktail;

import java.util.LinkedList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;

import lombok.Data;

import org.dhbw.cocktail.mixer.ICocktailMixer;

/**
 * Named Queries to Prevent SQL-Injection-like vulnerabilities
 */
@NamedQueries({
		@NamedQuery(name = "all_cocktails", query = "SELECT c FROM jc_cocktail c"),
		@NamedQuery(name = "search_cocktail", query = "SELECT c FROM jc_cocktail c WHERE UPPER(c.Name) LIKE :searchTerm ORDER BY c.Name ASC"),
		@NamedQuery(name = "search_cocktail_by_id", query = "SELECT c FROM jc_cocktail c WHERE c.id=:searchTerm"),
		@NamedQuery(name = "search_cocktails_by_ingredient_id", query = "SELECT c FROM jc_cocktail c, jc_ingredient i, jc_used_ingredient ui WHERE c.id=ui.RefCocktail and ui.Ingredient=i.id and i.id=:ingredient_id ORDER BY c.Name ASC")})
		
/**
 * A Class, that represents a Cocktail-Receipt. It contains its name, if its alcoholic, the type of the cocktail and the ingredients
 * that are required to mix it. Setter/getter/contructors are created by the lombok-project. 
 * 
 * @author Roland von Werden
 * @version 0.1
 *
 */
@Data
@Entity(name = "jc_cocktail")
public class Cocktail {

	/** ID for java.persistence */
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long Id;

	/** Name of the cocktail */
	@Column(name = "name")
	private String Name;
	
	@Column(name="description", length = 4000)
	private String Description;

	/** Type of the cocktail */
	@ManyToOne
	private CocktailType Type;

	/** Is the cocktail alcoholic? */
	@Column(name = "alcoholic")
	private boolean Alcoholic;

	@OneToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST,
			CascadeType.ALL }, orphanRemoval = true, mappedBy = "RefCocktail")
	// @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE}) // Wenn Hibernate ohne JPA verwendet wird
	public List<UsedIngredient> IngredientsUsed;

	public Cocktail() {
		this.IngredientsUsed = new LinkedList<UsedIngredient>();
	}

	public Cocktail(String name, CocktailType type, boolean alcoholic) {
		this.IngredientsUsed = new LinkedList<UsedIngredient>();
		this.Alcoholic = alcoholic;
		this.Name = name;
		this.Type = type;
	}

	/**
	 * Add an ingredient to the cocktail
	 * @param ingredient ingredient to be added
	 * @param amount needed amount
	 */
	public void addIngredient(Ingredient ingredient, double amount) {
		this.IngredientsUsed.add(new UsedIngredient(ingredient, amount, this));
	}

	/**
	 * Remove an ingredient from the cocktail
	 * @param ingredient
	 */
	public void removeIngredient(Ingredient ingredient) {
		for (int i=0;i<this.IngredientsUsed.size() ;i++) {
			if (this.IngredientsUsed.get(i).getIngredient().getId() == ingredient.getId()) {
				this.IngredientsUsed.remove(i);
				return;
			}
		}
	}

	/**
	 * Proxy-Method for mixing the cocktail
	 * @param count
	 * @param mixer
	 * @return
	 */
	public boolean mix(int count, ICocktailMixer mixer) {
		return mixer.mixCocktail(this, count);
	}

}